package code_analysis

import (
	"gitee.com/huanminabc/go-utils/common"
	"strconv"
	"strings"
)

/**
 * 将字符串内部指定" ' ( [  等对等符号内数据提取  替换成占位符@@str,并返回替换后的字符串和字符串map
 * @param str string 需要处理的字符串
 * @param symbol uint8 需要提取的符号
 * @return map[string]string(提取的占位符和内容)    , string(转换后的字符串)
 */
func PickBoth(str string, symbol uint8) (map[string]string, string) {
	var mapStr = make(map[string]string)
	for i := 0; i < len(str); i++ {
		//判断是否是字符串
		if str[i] == symbol {
			var startIndex int = i
			var endIndex int
			var num = 1
			//向右找到下一个"
			for j := i + 1; j < len(str); j++ {
				if str[j] == symbol {
					num--
				}
				if num == 0 {
					endIndex = j
					break
				}
			}
			if endIndex == 0 {
				//如果没有找到,则直接返回
				break
			}
			//截取字符串
			var newStr = str[startIndex : endIndex+1]
			//使用占位符funci替换
			var key = "@@str" + strconv.Itoa(i) + common.RandStringRunes()
			str = str[:startIndex] + key + str[endIndex+1:]
			//将字符串放入map中
			mapStr[key] = newStr
		}
	}
	return mapStr, str
}

// 将函数表达式替换成占位符,并返回替换后的字符串和函数表达式map
func FuncPickBoth(str string) (map[string]string, string) {
	var mapFunc = make(map[string]string)
	for i := 1; i < len(str); i++ {
		//判断是否是函数
		if str[i] == '(' && IsVariableNameRule(string(str[i-1])) {
			var startIndex int
			var endIndex int
			var num = 1
			//向左找直到不等于正则表达式\w
			for j := i - 1; j >= 0; j-- {
				if !IsVariableNameRule(string(str[j])) {
					startIndex = j + 1
					break
				}
			}
			//向右找到)的位置
			for j := i + 1; j < len(str); j++ {
				if str[j] == '(' {
					num++
				}
				if str[j] == ')' {
					num--
				}
				if num == 0 {
					endIndex = j
					break
				}
			}
			//截取函数
			var funcStr = str[startIndex : endIndex+1]
			var key = "@@func" + strconv.Itoa(i) + common.RandStringRunes()
			//使用占位符funci替换
			str = str[:startIndex] + key + str[endIndex+1:]
			//将函数放入map中
			mapFunc[key] = funcStr
		}
	}
	return mapFunc, str
}

/**
 *还原pickBoth的字符串字符串
 * @param str string 需要处理的字符串 ,这个字符串是pickBoth处理后的字符串
 * @param mapStr map[string]string(提取的占位符和内容)
 */
func RestorePickBoth(str string, mapStr map[string]string) string {
	for k, v := range mapStr {
		str = strings.ReplaceAll(str, k, v)
	}
	return str
}

// 截取字符串内部${}的变量
func GetStrBigBrackets(str string) ([]string, bool) {
	//判断是否有${}
	if strings.Index(str, "${") == -1 || strings.Index(str, "}") == -1 {
		return nil, false
	}
	//判断{}是否成对出现
	if strings.Count(str, "{") != strings.Count(str, "}") {
		panic("字符串中的{}不成对出现")
	}
	var result []string
	var num = 0
	var startIndex = 0
	var endIndex = 0
	for i := 0; i < len(str); i++ {
		if string(str[i]) == "$" && string(str[i+1]) == "{" {
			num++
			if num == 1 {
				startIndex = i + 1
			}
		}
		if string(str[i]) == "}" {
			num--
			if num == 0 {
				endIndex = i
				result = append(result, str[startIndex+1:endIndex])
			}
		}
	}
	return result, true
}

// 判断字符串是否存在$,并且获取$xx
func GetStrDollar(str string) string {
	index := strings.Index(str, "$")
	if index != -1 {
		//从$后面开始截取是数字的
		str = str[index+1:]
		end := len(str)
		//找到第一个不是数字的
		for i, v := range str {
			if v < '0' || v > '9' {
				end = i
				break
			}
		}
		str = str[:end]
		return "$" + str
	}
	return ""
}

// 判断字符串是否存在#,并且获取#xx
func GetStrSharp(str string) string {
	index := strings.Index(str, "#")
	if index != -1 {
		//从#后面开始截取是数字的
		str = str[index+1:]
		end := len(str)
		//找到第一个不是数字的
		for i, v := range str {
			if v < '0' || v > '9' {
				end = i
				break
			}
		}
		str = str[:end]
		return "#" + str
	}
	return ""
}
